package priv.conceit.study.leetcode.medium;

import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.Semaphore;

/**
 * 编号：1115
 * 交替打印Foo Bar
 * 基于信号量 重复测试
 *
 * <a href="https://leetcode-cn.com/problems/print-foobar-alternately/">
 * @author: conceit
 * @date: 2019/11/1 15:00
 */
public class PrintFoobarAlternately3 {

	Semaphore foo;
	Semaphore bar;

	/**
	 *
	 * 两个线程进行交替打印，则设定两个信号量foo,bar
	 * foo直接调用，bar调用前先进行阻塞
	 *
	 * {@link Semaphore#acquire()} 线程进行阻塞 申请许可
	 * {@link Semaphore#release()} 线程进行释放 创建许可
	 *
	 * @author conceit
	 * @date 2020/9/1 18:30
	 */
	public static void main(String[] args) throws Exception {
		PrintFoobarAlternately3 foobar3=new PrintFoobarAlternately3();
		new Thread(()->{
			try {
				foobar3.bar(()->System.out.println("bar"));
			} catch (BrokenBarrierException e) {
				e.printStackTrace();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}).start();

		new Thread(()->{
			try {
				foobar3.foo(()->System.out.println("foo"));
			} catch (BrokenBarrierException e) {
				e.printStackTrace();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}).start();
	}

	/**
	 * 实例化
	 * 初始本类的两个信号量对象 foo bar
	 */
	public PrintFoobarAlternately3() {
		foo=new Semaphore(1);
		bar=new Semaphore(0);
	}

	public void foo(Runnable printFoo) throws InterruptedException, BrokenBarrierException {
		for(int i=0;i<10;i++){
			foo.acquire();
			printFoo.run();
			bar.release();
		}
	}

	public void bar(Runnable printBar) throws BrokenBarrierException, InterruptedException {
		for(int i=0;i<10;i++){
			bar.acquire();
			printBar.run();
			foo.release();
		}
	}
}
